package Puzzle.UI;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GameJFrame extends JFrame implements KeyListener, ActionListener {
    //游戏主界面
    private int[][] data = new int[4][4];   //存放图片序号
    int x;
    int y;      //用于记录空白方块的位置
    //定义表示胜利的数组
    private int[][] win = new int[][]{
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };

    private int stepCount;   //统计步数

    //创建菜单项的条目
    private JMenuItem replayItem = new JMenuItem("重新游戏");
    private JMenuItem closeItem = new JMenuItem("关闭游戏");

    private JMenuItem aboutGameItem = new JMenuItem("关于游戏");
    private JMenuItem beauty = new JMenuItem("Beauty");
    private JMenuItem animal = new JMenuItem("Animal");
    private JMenuItem sports = new JMenuItem("Sports");

    private String pictureChoice = "animal";        //关于图片的选择
    private int no = 3;         //表示第几张图片

    public GameJFrame() {
        //初始化窗口
        initJFrame();
        //初始化菜单
        initJMenuBar();
        //初始化随机数据  用以打乱图片
        initData();
        //初始化图片
        initPicture();

        //显示窗口  一般写在最后
        this.setVisible(true);
    }

    private void initData() {
        int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        Random r = new Random();
        //打乱数据 -- 利用随机索引打乱
        for (int i = 0; i < 16; i++) {
            int index = r.nextInt(arr.length);
            int temp = arr[i];
            arr[i] = arr[index];
            arr[index] = temp;
        }

        //将一维数组中的数据 放到data数组中
        for (int i = 0; i < arr.length; i++) {
            //获取空白方块的位置
            if (arr[i] == 0) {
                x = i / 4;
                y = i % 4;
            }
            data[i / 4][i % 4] = arr[i];
        }
    }

    private void initPicture() {
        //注意：先加载的图片 会在上方 后加载的图片 会在它的下面

        //清空当前所有图片
        this.getContentPane().removeAll();

        //加载胜利图片
        if (isVictory()) {
            JLabel winJLabel = new JLabel(new ImageIcon("./images/puzzle/win.png"));
            winJLabel.setBounds(203, 283, 197, 73);
            this.getContentPane().add(winJLabel);
        }

        //加载步数显示
        JLabel step = new JLabel("步数：" + stepCount);
        step.setBounds(50, 30, 150, 40);
        this.getContentPane().add(step);

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                //随机获取一张图片
                int number = data[i][j];
                //创建image对象
                ImageIcon icon = new ImageIcon("./images/puzzle/" + pictureChoice+ "/" + pictureChoice + no + "/" + number + ".jpg");
                //创建label管理图片
                JLabel jLabel = new JLabel(icon);
                //设置图片位置
                jLabel.setBounds(j * 105 + 83, i * 105 + 134, 105, 105);
                //为图片添加边框
                //1:表示使图片呈现凹进去的效果
                jLabel.setBorder(new BevelBorder(1));
                //添加到主界面中
                this.getContentPane().add(jLabel);
            }
        }

        //添加背景图片
        ImageIcon bg = new ImageIcon("./images/puzzle/background.png");
        JLabel background = new JLabel(bg);
        background.setBounds(40, 40, 508, 560);
        this.getContentPane().add(background);

        //刷新界面
        this.getContentPane().repaint();
    }

    private void initJMenuBar() {
        //创建菜单栏
        JMenuBar jMenuBar = new JMenuBar();

        //创建菜单项
        JMenu functionMenu = new JMenu("功能");
        JMenu tipsMenu = new JMenu("说明");
        JMenu changeImage = new JMenu("更换图片");

        //各条目添加动作监听
        replayItem.addActionListener(this);
        closeItem.addActionListener(this);
        aboutGameItem.addActionListener(this);
        beauty.addActionListener(this);
        animal.addActionListener(this);
        sports.addActionListener(this);

        //添加条目到各菜单项
        functionMenu.add(replayItem);
        functionMenu.add(changeImage);
        functionMenu.add(closeItem);
        changeImage.add(beauty);
        changeImage.add(animal);
        changeImage.add(sports);

        tipsMenu.add(aboutGameItem);

        //添加菜单项到菜单栏中
        jMenuBar.add(functionMenu);
        jMenuBar.add(tipsMenu);

        //添加菜单栏到窗口中
        this.setJMenuBar(jMenuBar);
    }

    private void initJFrame() {
        this.setSize(603, 680);
        this.setTitle("Puzzle Game v1.0");
        this.setAlwaysOnTop(true);
        this.setLocationRelativeTo(null);
        //3表示关闭一个窗口，程序就会结束
        this.setDefaultCloseOperation(3);
        //关闭图片默认居中显示
        this.setLayout(null);
        //添加键盘操作的事件
        this.addKeyListener(this);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        //判断游戏是否胜利 若胜利 不再允许操作
        if (isVictory()) return;

        int code = e.getKeyCode();
        //A -> 65
        if (code == 65) {
            //清空界面的所有图片
            this.getContentPane().removeAll();
            //重新加载一张完整的图片
            JLabel all = new JLabel(new ImageIcon("./images/puzzle/" + pictureChoice + "/" + pictureChoice + no + "/all.jpg"));
            all.setBounds(83, 134, 420, 420);
            this.getContentPane().add(all);
            //重新添加背景图片
            ImageIcon bg = new ImageIcon("./images/puzzle/background.png");
            JLabel background = new JLabel(bg);
            background.setBounds(40, 40, 508, 560);
            this.getContentPane().add(background);

            //刷新界面
            this.getContentPane().repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        //判断游戏是否胜利 若胜利 不再允许操作
        if (isVictory()) return;

        //实现键盘上下左右-操作拼图移动
        int code = e.getKeyCode();
        //向左移动
        if (code == 37) {
            //边界条件
            if (y == 3)
                return;
            data[x][y] = data[x][y + 1];
            data[x][y + 1] = 0;
            y++;    //更新空白图片的坐标
            //每移动一次，stepCount加一
            stepCount++;
            initPicture();      //重新加载图片
        }
        //向上移动
        else if (code == 38) {
            //边界条件
            if (x == 3)
                return;
            //System.out.println("向上移动");
            data[x][y] = data[x + 1][y];
            data[x + 1][y] = 0;
            x++;    //更新空白图片的坐标
            //每移动一次，stepCount加一
            stepCount++;
            initPicture();      //重新加载图片
        }
        //向右移动
        else if (code == 39) {
            //边界条件
            if (y == 0)
                return;
            data[x][y] = data[x][y - 1];
            data[x][y - 1] = 0;
            y--;    //更新空白图片的坐标
            //每移动一次，stepCount加一
            stepCount++;
            initPicture();      //重新加载图片
        }
        //向下移动
        else if (code == 40) {
            //边界条件
            if (x == 0)
                return;
            data[x][y] = data[x - 1][y];
            data[x - 1][y] = 0;
            x--;    //更新空白图片的坐标
            //每移动一次，stepCount加一
            stepCount++;
            initPicture();      //重新加载图片
        } else if (code == 65) {   //press A -> 显示完整图片
            initPicture();
        } else if (code == 87) {   //press W -> 一键通关
            data = new int[][]{
                    {1, 2, 3, 4},
                    {5, 6, 7, 8},
                    {9, 10, 11, 12},
                    {13, 14, 15, 0}
            };
            initPicture();
        }
    }

    //判断游戏是否胜利
    public boolean isVictory() {
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[0].length; j++) {
                if (data[i][j] != win[i][j]) return false;
            }
        }
        return true;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //获取当前鼠标点击的对象
        Object obj = e.getSource();
        if (obj == replayItem) {
            //重新游戏
            stepCount = 0;      //计步器清零
            initData();         //重新打乱图片
            initPicture();      //重新加载图片
        } else if (obj == closeItem) {
            //关闭游戏
            System.exit(0);     //直接关闭虚拟机 退出游戏
        } else if (obj == aboutGameItem) {
            //关于游戏
            //创建弹框对象
            JDialog jDialog = new JDialog();
            //创建JLabel对象
            JLabel jLabel = new JLabel("关于游戏的快捷键：" + "A：摁住不松可查看" +
                    "还原后的完整图片，松开后返回游戏" +
                    " W：一键通关");
            jLabel.setBounds(0, 0, 480, 480);  //jLabel设置大小
            jDialog.getContentPane().add(jLabel);       //添加jLabel
            jDialog.setSize(550, 200);       //弹框设置大小
            jDialog.setAlwaysOnTop(true);              //弹框置顶
            jDialog.setLocationRelativeTo(null);    //弹框居中
            jDialog.setModal(true);         //不关闭弹框无法进行游戏
            jDialog.setVisible(true);       //显示弹框
        }else if (obj == beauty){
            //选择了beauty类的图片
            pictureChoice = "girl";
            Random r = new Random();
            no = r.nextInt(6) + 1;
            //重新加载游戏
            stepCount = 0;
            initData();
            initPicture();
        }else if (obj == animal){
            //选择了animal类的图片
            pictureChoice = "animal";
            Random r = new Random();
            no = r.nextInt(8) + 1;
            //重新加载游戏
            stepCount = 0;
            initData();
            initPicture();
        }else if (obj == sports){
            //选择了sports类的图片
            pictureChoice = "sport";
            Random r = new Random();
            no = r.nextInt(10) + 1;
            //重新加载游戏
            stepCount = 0;
            initData();
            initPicture();
        }
    }
}
